package com.harveyguo.nihonngo.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import cn.dev33.satoken.util.SaResult;
import com.harveyguo.nihonngo.exception.BizException;
import com.harveyguo.nihonngo.exception.ExceptionType;
import com.harveyguo.nihonngo.model.BaseEntity;
import com.harveyguo.nihonngo.model.dto.UserCreateDto;
import com.harveyguo.nihonngo.model.dto.UserDto;
import com.harveyguo.nihonngo.model.entity.User;
import com.harveyguo.nihonngo.model.mapper.UserMapper;
import com.harveyguo.nihonngo.repositories.UserRepository;
import com.harveyguo.nihonngo.service.UserService;
import com.harveyguo.nihonngo.utils.EncoderUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

@Service
public class UserServiceImpl implements UserService {

    UserRepository repository;

    UserMapper userMapper;

    @Override
    public List<UserDto> list() {
        return this.repository.findAll().stream().map(userMapper::toDto).collect(Collectors.toList());
    }

    @Override
    public UserDto createdUser(UserCreateDto userCreateDto) {
        checkUsername(userCreateDto.getUsername());
        User user = userMapper.CreatUser(userCreateDto);
        user.setPassword(EncoderUtils.passwordEncoder(user.getPassword()));
        return userMapper.toDto(repository.save(user));
    }

    @Override
    public BaseEntity<UserDto> login(UserCreateDto userCreateDto) {
        Optional<User> byUsername = repository.findByUsername(userCreateDto.getUsername());
        if (byUsername.isPresent()) {
            User user = byUsername.get();
            if (EncoderUtils.passwordEncoder(userCreateDto.getPassword()).equals(user.getPassword())) {
                StpUtil.login(user.getId());
                // 在登录时缓存user对象
                // StpUtil.getSession().set("userId", user.getId());
                user.setToken(StpUtil.getTokenValue());
                return new BaseEntity<>(userMapper.toDto(user), "登录成功");
            }
        }
        throw new BizException(ExceptionType.USER_LOGIN_ERROR);
    }

    private void checkUsername(String name) {
        Optional<User> byUsername = repository.findByUsername(name);
        if (byUsername.isPresent()) {
            throw new BizException(ExceptionType.USER_NAME_DUPLICATE);
        }
    }

    @Override
    public UserDto findById(String id) {
        Optional<User> user = repository.findById(id);
        if (user.isPresent()) {
            return userMapper.toDto(user.get());
        }
        throw new BizException(ExceptionType.USER_NOT_FOUND);
    }

    @Override
    public UserDto updateUser(String id, UserCreateDto userDto) {
        Optional<User> userOpt = repository.findById(id);
        if (userOpt.isPresent()) {
            User user = userOpt.get();
            // 更新用户信息
            if (userDto.getNickname() != null)
                user.setNickname(userDto.getNickname());
            if (userDto.getEmail() != null)
                user.setEmail(userDto.getEmail());
            if (userDto.getPhone() != null)
                user.setPhone(userDto.getPhone());
            if (userDto.getAvatar() != null)
                user.setAvatar(userDto.getAvatar());
            if (userDto.getGender() != null)
                user.setGender(userDto.getGender());
            if (userDto.getUserType() != null)
                user.setUserType(userDto.getUserType());
            if (userDto.getAge() != null)
                user.setAge(userDto.getAge());
            if (userDto.getWeight() != null)
                user.setWeight(userDto.getWeight());
            if (userDto.getHeight() != null)
                user.setHeight(userDto.getHeight());
            if (userDto.getBoxingLevel() != null)
                user.setBoxingLevel(userDto.getBoxingLevel());
            if (userDto.getExperienceYears() != null)
                user.setExperienceYears(userDto.getExperienceYears());
            if (userDto.getPreferredStyle() != null)
                user.setPreferredStyle(userDto.getPreferredStyle());
            if (userDto.getIntroduction() != null)
                user.setIntroduction(userDto.getIntroduction());

            return userMapper.toDto(repository.save(user));
        }
        throw new BizException(ExceptionType.USER_NOT_FOUND);
    }

    @Override
    public void deleteUser(String id) {
        if (repository.existsById(id)) {
            repository.deleteById(id);
        } else {
            throw new BizException(ExceptionType.USER_NOT_FOUND);
        }
    }

    @Override
    public List<UserDto> findByBoxingLevel(String boxingLevel) {
        return repository.findByBoxingLevel(boxingLevel).stream()
                .map(userMapper::toDto)
                .collect(Collectors.toList());
    }

    @Override
    public List<UserDto> findByExperienceYears(Integer years) {
        return repository.findByExperienceYears(years).stream()
                .map(userMapper::toDto)
                .collect(Collectors.toList());
    }

    @Override
    public List<UserDto> findByPreferredStyle(String preferredStyle) {
        return repository.findByPreferredStyle(preferredStyle).stream()
                .map(userMapper::toDto)
                .collect(Collectors.toList());
    }

    @Override
    public List<UserDto> findNearbyUsers(Double latitude, Double longitude, Double radius) {
        return repository.findNearbyUsers(latitude, longitude, radius).stream()
                .map(userMapper::toDto)
                .collect(Collectors.toList());
    }

    @Autowired
    public void setRepository(UserRepository repository) {
        this.repository = repository;
    }

    @Autowired
    public void setUserMapper(UserMapper userMapper) {
        this.userMapper = userMapper;
    }
}
